package com.oss.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;


@Component
@Slf4j
public class ZipUtils {
    @Autowired
    HttpServletResponse response;
    /**
     * 替换某个 item,
     * @param zipInputStream zip文件的zip输入流
     * @param zipOutputStream 输出的zip输出流
     * @param itemName 要替换的 item 名称
     * @param itemInputStream 要替换的 item 的内容输入流
     */
    public  void replaceItem(ZipInputStream zipInputStream,
                                   ZipOutputStream zipOutputStream,
                                   String itemName,
                                   InputStream itemInputStream
    ){
        //
        if(null == zipInputStream){return;}
        if(null == zipOutputStream){return;}
        if(null == itemName){return;}
        if(null == itemInputStream){return;}
        //
        ZipEntry entryIn;
        try {
            while((entryIn = zipInputStream.getNextEntry())!=null)
            {
                String entryName =  entryIn.getName();
                ZipEntry entryOut = new ZipEntry(entryName);
                // 只使用 name
                zipOutputStream.putNextEntry(entryOut);
                // 缓冲区
                byte [] buf = new byte[8*1024];
                int len;

                if(entryName.equals(itemName)){
                    // 使用替换流
                    while((len = (itemInputStream.read(buf))) > 0) {
                        zipOutputStream.write(buf, 0, len);
                    }
                } else {
                    // 输出普通Zip流
                    while((len = (zipInputStream.read(buf))) > 0) {
                        zipOutputStream.write(buf, 0, len);
                    }
                }
                // 关闭此 entry
                zipOutputStream.closeEntry();

            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //e.printStackTrace();
            close(itemInputStream);
            close(zipInputStream);
            close(zipOutputStream);
        }
    }

    /**
     * 包装输入流
     */
    public  ZipInputStream wrapZipInputStream(InputStream inputStream){
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        return zipInputStream;
    }

    /**
     * 包装输出流
     */
    public  ZipOutputStream wrapZipOutputStream(OutputStream outputStream){
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream, StandardCharsets.ISO_8859_1);
        return zipOutputStream;
    }
    private  void close(InputStream inputStream){
        if (null != inputStream){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private  void close(OutputStream outputStream){
        if (null != outputStream){
            try {
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 文件压缩到zip
     * @param list  待压缩的文件路径数组
     * @param zipName 压缩包的名称(全路径)
     * @throws Exception
     */
    public  void fileToZip(List<String> list,String zipName) throws Exception {
        // 多个文件zip下载
        response.setContentType("application/zip");
        //设置响应头，以附件的形式下载
        response.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(zipName,"UTF-8"));
        ZipOutputStream zos = null;
        BufferedInputStream bis = null;
        FileInputStream fis = null;
        try{
            zos = new ZipOutputStream(response.getOutputStream());
            byte[] buf = new byte[8192];
            int len;
            // 遍历数组中的数据
            for (String path : list) {
                File file = new File(path);
                // 将word文件添加到压缩包中去
                if (file != null && file.isFile() && file.exists()) {
                    // 自定义压缩的名称
                    ZipEntry ze = new ZipEntry(file.getName());
                    zos.putNextEntry(ze);
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    // 判断流中的数据不为0将文件添加到压缩包
                    while ((len = bis.read(buf)) > 0) {
                        zos.write(buf, 0, len);
                    }
                    bis.close();
                    fis.close();
                    zos.closeEntry();
                }

            }
            zos.close();
        }catch(Exception ex){
            ex.printStackTrace();
        }finally {
            if(bis != null){
                try{
                    bis.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try{
                    fis.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            if(zos != null){
                try{
                    zos.close();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            response.getOutputStream().close();
            delteComparessFile(list);
        }
    }

    // 删除文件夹
    public void delteComparessDir(File dir){
        File[] files = dir.listFiles();
        if(files != null){
            for(File f:files) {
                if (f.isDirectory()){
                    delteComparessDir(f);
                } else {
                    // 先设置文件的可写权限
                    f.setWritable(true);
                    boolean b = FileUtils.deleteQuietly(f);
                    log.info("delteComparessDir-删除文件是否成功="+b+"文件路径"+f.getPath());
                }
            }
        }
        dir.setWritable(true);
        dir.delete(); // 删除文件夹
    }
    // 删除文件列表
    public void delteComparessFile(List<String> list){
        if(list != null){
            for(String path:list) {
                File f = new File(path);
                if (f.exists()){
                    if (f.isDirectory()){
                        delteComparessDir(f);
                    } else {
                        // 先设置文件的可写权限
                        f.setWritable(true);
                        boolean b = FileUtils.deleteQuietly(f);
                        log.info("delteComparessFile-删除文件是否成功="+b+"文件路径"+f.getPath());
                    }
                }
            }
        }
    }

}